package com.me.study.simpleMapperScan;

import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

/**
 * Mybatis-MapperScan 的 基本原理：根据接口类型修改 bean定义为 工厂bean，并注册到 spring工厂。	<p>
 * MyImportBeanDefinitionRegistrar 注册器本身不会被注册为 Spring Bean。		<p></p>
 *
 * @author ME
 * @date   2019/12/30
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		ConstructorArgumentValues constructorArgumentValues =
				registry.getBeanDefinition("indexServiceImpl1").getConstructorArgumentValues();

		// 得到 bean定义，并注册到 bean工厂中
		AnnotationAttributes mapperScanAttrs = AnnotationAttributes
				.fromMap(importingClassMetadata.getAnnotationAttributes(MyMapperScan.class.getName()));
		if (mapperScanAttrs != null) {
			// 拿到包路径，然后假装扫描并注册到 bean工厂中
			System.out.println("@MyMapperScan 配置了要扫描的包路径：" + mapperScanAttrs.getStringArray("basePackages")[0]);
		}

		// 假设扫描到了 UserDao
		Class<UserDao> clazz = UserDao.class;
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition();
		// 自定义 beanDefinition的 BeanClass 为 工厂bean
		beanDefinition.setBeanClass(DaoFactoryBean.class);
		// 自定义 beanDefinition 的构造函数，设置为一个有参构造：DaoFactoryBean.DaoFactoryBean(Class)
		// beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("UserDao");
		beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(clazz.getName());

		// beanName = userDao
		AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
		registry.registerBeanDefinition(beanNameGenerator.generateBeanName(beanDefinition, registry), beanDefinition);
	}
}
